#include "KcTexWhitespaceNode.h"
#include "../KvPaint.h"
#include "KuUtf8.h"


KcTexWhitespaceNode::KcTexWhitespaceNode(KeType type, unsigned count, KvTexNode* parent)
    : super_(parent)
    , type_(type)
    , count_(count)
{

}


std::string KcTexWhitespaceNode::getTypeName() const
{
    return "TexWhitespaceNode";
}


KcTexWhitespaceNode::KpSize KcTexWhitespaceNode::getSize(KvPaint& paint) const
{
    static const std::string space0(" ");
    static const std::string space1(KuUtf8::fromWChar(0x2003));

    // TODO: use horizontalAdvance
    auto sz = getSizeNavie_(paint, (type_ == k_normal || type_ == k_nonbreaking) ? space0 : space1);
    sz.width *= count_;

    switch (type_) 
    {
    case k_1en: sz.width /= 2; break;
    case k_hair: sz.width *= (1.0 / 12.0); break;
    case k_thin: sz.width *= (1.0 / 6.0); break;
    case k_negthin: sz.width *= (-1.0 /6.0); break;
    case k_medium: sz.width *= (2.0 / 9.0); break;
    case k_negmedium: sz.width *= (-2.0 / 9.0); break;
    case k_thick: sz.width *= (5.0 / 18.0); break;
    case k_negthick: sz.width *= (-5.0 / 18.0); break;
    case k_thicker: sz.width *= (1.0 / 3.0); break;
    default: break;
    }

    return sz;
}


double KcTexWhitespaceNode::draw(KvPaint& paint, double x, double y) const
{
    super_::draw(paint, x, y);
    return x + getSize(paint).width;
}


std::map<std::string_view, KcTexWhitespaceNode::KeType> KcTexWhitespaceNode::supportedInstructions_;

#include <mutex>
void KcTexWhitespaceNode::initInstructions_()
{
    static std::mutex sMutex;
    std::lock_guard<std::mutex> lock(sMutex);
    if (supportedInstructions_.empty()) {
        supportedInstructions_[" "] = k_thicker;
        supportedInstructions_["nbsp"] = k_nonbreaking;
        supportedInstructions_["enspace"] = k_1en;
        supportedInstructions_["enskip"] = k_1en;
        supportedInstructions_["quad"] = k_quad;
        supportedInstructions_["emspace"] = k_quad;
        //supportedInstructions_["qquad"] = k_quad; // * 2
        supportedInstructions_[","] = k_thin;
        supportedInstructions_["thinspace"] = k_thin;
        supportedInstructions_[":"] = k_medium;
        supportedInstructions_["medspace"] = k_medium;
        supportedInstructions_[";"] = k_thick;
        supportedInstructions_["thickspace"] = k_thick;
        supportedInstructions_["!"] = k_negthin;
        supportedInstructions_["negthinspace"] = k_negthin;
        supportedInstructions_["negmedspace"] = k_negmedium;
        supportedInstructions_["negthickspace"] = k_negthick;
    }
}


KcTexWhitespaceNode::KeType KcTexWhitespaceNode::str2Type(const std::string_view& str)
{
    initInstructions_(); // TODO:
    auto pos = supportedInstructions_.find(str);
    return pos == supportedInstructions_.cend() ? k_unknown : pos->second;
}
